" Can be windows or linux
let platform  = "windows"
let mapleader = " "

"[=======================================================COMMON-SETTINGS START========================================================
" Can copy&paste between vim and system clipboard
set clipboard =unnamedplus
set number
set relativenumber
set showcmd
set cmdheight =2
set wildmenu
set cursorline
set mouse     =a
"set guicursor=n-v-c:ver25,i-ci-ve:ver25,r-cr:hor20,o:hor50,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor,sm:block-blinkwait175-blinkoff150-blinkon175
" Open the regex search
set magic
set scrolloff =5
"=======================================================COMMON-SETTINGS   END========================================================]

"[=======================================================TAB-SETTINGS START========================================================
" Indent by 4 spaces when using >>, <<, == etc.
set shiftwidth  =4
" Indent by 4 spaces when pressing <TAB>
set softtabstop =4
" Use softtabstop spaces instead of tab characters for indentation
set expandtab
" Keep indentation from previous line
set autoindent
" Automatically inserts indentation in some cases
set smartindent
" Like smartindent, but stricter and more customisable
set cindent
"=======================================================TAB-SETTINGS   END========================================================]

"[==================================================NOT-KNOWN-YET START==================================================
set hidden
set nobackup
set nowritebackup
set updatetime  =300
set shortmess  +=c
set signcolumn  =yes
"===================================================NOT-KNOWN-YET  END===================================================]

"[==================================================COMMON-KEY-MAP START==================================================
" noremap <C-e> 5<C-e>
" noremap <C-y> 5<C-y>
map s <nop>
map S :w<CR>
map Q :q<CR>
map J 5j
map K 5k
map H 0
map L $
map <C-j> <C-e>
map <C-k> <C-y>
map W 5w
map B 5b
map U <C-r>
" Indentation
nnoremap < <<
nnoremap > >>
" Move cursor to the end of the line in insert mode
inoremap <C-a> <ESC>A
" Ctrl+i in insert mode be used for inserting a tab by default, this key combination has conflict with TAB
"map <C-i> <NOP>
"inoremap <C-i> <ESC>I
" Use Ctrl+l in inser mode for del, Ctrl+h map to backspace and Ctrl+j map to <CR> by default,
inoremap <C-l> <DEL>
" Spelling check, can use [s or ]s to find last or next spelling error, use z= to open the vocabulary list
map <LEADER>sc :set spell!<CR>
" jump to next <++> and edit it,<++> is a placeholder
map <LEADER><LEADER> <ESC>/<++><CR>:nohlsearch<CR>c4l
" Cancel the highlight of search result, the default key is <CR-[>
" noremap <LEADER>nhl :nohlsearch<CR>
" if maparg('<C-L>', 'n') ==# '' | nnoremap <silent> <C-L> :nohlsearch<CR><C-L> | endif
nnoremap <silent><ESC> :nohlsearch<CR>
" Paste last copy text
noremap <LEADER>p "0p
"==================================================COMMON-KEY-MAP END==================================================]

"[===========================================SPLITED-WINDOWS-KEY-MAP START==============================================
" split the windows
map sl :set splitright<CR>:vsplit<CR>
map sh :vsplit<CR>
map sk :split<CR>
map sj :set splitbelow<CR>:split<CR>
" Jump to right split window
map <LEADER>l <C-w>l
map <LEADER>h <C-w>h
map <LEADER>j <C-w>j
map <LEADER>k <C-w>k
" Move the windows to the very top
map <LEADER>H <C-w>H
map <LEADER>J <C-w>J
map <LEADER>K <C-w>K
map <LEADER>L <C-w>L
" Add the split window size
map <LEADER><UP>    :res +5<CR>
map <LEADER><DOWN>  :res -5<CR>
map <LEADER><LEFT>  :vertical resize -5<CR>
map <LEADER><RIGHT> :vertical resize +5<CR>
" Close the window
map <C-w>c :close<CR>
" Close all windows but this
map <C-w>o :only<CR>
"=========================================SPLITED-WINDOWS-KEY-MAP START============================================]

"[============================================TAB-PAGE-MAP START==============================================
" Jump between tab pages
map th :-tabnext<CR>
map tl :+tabnext<CR>
map tH :1tabnext<CR>
map tL :$tabnext<CR>
" Move the tab page to left or right
map tmh :-tabmove<CR>
map tml :+tabmove<CR>
"=================================================TAB-PAGE-MAP END===========================================

"[=========================================LOAD-PLUG-INS START=============================================
if (platform=="windows")
    call plug#begin('D:\ProgramFiles\GlobalScoopApps\apps\neovim\current\share\nvim\runtime\plugged')
endif
if (platform=="linux")
    if empty(glob("~/.config/nvim/autoload/plug.vim"))
        silent !curl -flO ~/.config/nvim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
        autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
    endif
    call plug#begin('~/.config/nvim/autoload/plugged')
endif
        Plug 'vim-airline/vim-airline'
        Plug 'joshdick/onedark.vim'
        Plug 'neoclide/coc.nvim', {'branch': 'release'}
        Plug 'rhysd/vim-grammarous'
        Plug 'junegunn/vim-easy-align'
        Plug 'sheerun/vim-polyglot'     " For multiple language syntax
        Plug 'yuttie/comfortable-motion.vim'
        Plug 'MattesGroeger/vim-bookmarks'
        Plug 'preservim/nerdtree'
    call plug#end()
"=========================================LOAD-PLUG-INS END=============================================]

"[========================================COMPILE-AND-RNU START===================================
noremap <LEADER>r :call CompileRunGcc()<CR>
func! CompileRunGcc()
    exec "w"
    " Using clang to compile c and cpp, for if you install the llvm, you will get clang and the language server clangd at the same time. %< represent current file without filename extension.
    " You have to specific the lib path in your environment or in compile commands.json current workspace. In my windows, there are 3 paths should be added in 'LIB' environment:
    " 1. C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\lib\x64
    " 2. C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\um\x64
    " 3. C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64
    if &filetype == 'c'
        exec "!clang % -o %<.exe"
        exec "!%<.exe"
    elseif &filetype == 'cpp'
        set splitbelow
        exec "!g++ -std=c++11 % -Wall -o %<"
        :sp
        :res -15
        :term ./%<
    elseif &filetype == 'java'
        exec "!javac %"
        exec "!time java %<"
    elseif &filetype == 'sh'
        :!time bash %
    elseif &filetype == 'python'
        set splitbelow
        :sp
        :term python3 %
    elseif &filetype == 'html'
        silent! exec "!".g:mkdp_browser." % &"
    elseif &filetype == 'markdown'
        exec "MarkdownPreview"
    elseif &filetype == 'tex'
        silent! exec "VimtexStop"
        silent! exec "VimtexCompile"
    elseif &filetype == 'go'
        set splitbelow
        :sp
        :term go run %
    endif
endfunc
"========================================COMPILE-AND-RNU END===================================]

"[=======================================================ONEDARK.VIM START========================================================
"Use 24-bit (true-color) mode in Vim/Neovim when outside tmux.
"If you're using tmux version 2.2 or later, you can remove the outermost $TMUX check and use tmux's 24-bit color support
"(see < http://sunaku.github.io/tmux-24bit-color.html#usage > for more information.)
if (empty($TMUX))
  if (has("nvim"))
    "For Neovim 0.1.3 and 0.1.4 < https://github.com/neovim/neovim/pull/2198 >
    let $NVIM_TUI_ENABLE_TRUE_COLOR=1
  endif
  "For Neovim > 0.1.5 and Vim > patch 7.4.1799 < https://github.com/vim/vim/commit/61be73bb0f965a895bfb064ea3e55476ac175162 >
  "Based on Vim patch 7.4.1770 (`guicolors` option) < https://github.com/vim/vim/commit/8a633e3427b47286869aa4b96f2bfc1fe65b25cd >
  " < https://github.com/neovim/neovim/wiki/Following-HEAD#20160511 >
  if (has("termguicolors"))
    set termguicolors
  endif
endif
" onedark.vim override: Don't set a background color when running in a terminal;
" just use the terminal's background color
" `gui` is the hex color code used in GUI mode/nvim true-color mode
" `cterm` is the color code used in 256-color mode
" `cterm16` is the color code used in 16-color mode
if (has("autocmd") && !has("gui_running"))
  augroup colorset
    autocmd!
    let s:white = { "gui": "#ABB2BF", "cterm": "145", "cterm16" : "7" }
    autocmd ColorScheme * call onedark#set_highlight("Normal", { "fg": s:white }) " `bg` will not be styled since there is no `bg` setting
  augroup END
endif

if (has("autocmd"))
  augroup colorextend
    autocmd!
    " Make `Function`s bold in GUI mode
    autocmd ColorScheme * call onedark#extend_highlight("Function", { "gui": "bold" })
    " Override the `Statement` foreground color in 256-color mode
    autocmd ColorScheme * call onedark#extend_highlight("Statement", { "fg": { "cterm": 128 } })
    " Override the `Identifier` background color in GUI mode
    autocmd ColorScheme * call onedark#extend_highlight("Identifier", { "bg": { "gui": "#333333" } })
  augroup END
endif
"=======================================================ONEDARK.VIM END========================================================]

"[=======================================================COC.NVIM START========================================================
let g:coc_global_extensions = ['coc-python', 'coc-json']
" Use tab for trigger completion with characters ahead and navigate.
" Use command ':verbose imap <tab>' to make sure tab is not mapped by other plugin.
" This would catch a bug that I haven't figure it out, which is the <TAB> doesn't work if there is a character before the cursor. But if you use tab for 4 spaces, it will be fine, because you can just use spaces to replace tab.
inoremap <silent><expr> <TAB>
      \ pumvisible() ? "\<C-n>" :
      \ <SID>check_back_space() ? "\<TAB>" :
      \ coc#refresh()
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
function! s:check_back_space() abort
  let col = col('.') - 1
  return !col || getline('.')[col - 1]  =~# '\s'
endfunction
"Deprecated, because I think I can stand the tab bug
"inoremap <expr> <C-j> pumvisible() ? "\<C-n>" : "\<C-j>"
"inoremap <expr><C-k> pumvisible() ? "\<C-p>" : "\<C-k>"

" In windows, <C-SPACE> is for switching input method editor. <C-i> has been set for trigger completion by default, so it's not necessary
" inoremap <silent><expr> <c-space> coc#refresh()
nmap <silent> [c <Plug>(coc-diagnostic-prev)
nmap <silent> ]c <Plug>(coc-diagnostic-next)
" Remap keys for gotos
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
" Use K to show documentation in preview window
nnoremap <silent><LEADER>d :call <SID>show_documentation()<CR>
function! s:show_documentation()
  if (index(['vim','help'], &filetype) >= 0)
    execute 'h '.expand('<cword>')
  else
    call CocAction('doHover')
  endif
endfunction
" Remap for format selected region
xmap <leader>f  <Plug>(coc-format-selected)
nmap <leader>f  <Plug>(coc-format-selected)

"=======================================================COC.NVIM END========================================================]

"[=======================================================VIM-GRAMMAROUS START========================================================
map <LEADER>gc :GrammarousCheck<CR>
map [g <Plug>(grammarous-move-to-previous-error)<Plug>(grammarous-open-info-window)
map ]g <Plug>(grammarous-move-to-next-error)<Plug>(grammarous-open-info-window)
map <LEADER>gf <Plug>(grammarous-fixit)]g
"=======================================================VIM-GRAMMAROUS END========================================================]

"[=======================================================VIM-EASY-ALIGN START========================================================
" Start interactive EasyAlign in visual mode (e.g. vipga)
xmap ga <Plug>(EasyAlign)
" Start interactive EasyAlign for a motion/text object (e.g. gaip)
nmap ga <Plug>(EasyAlign)
"=======================================================VIM-EASY-ALIGN END=======================================================]

"[=======================================================COMFORTABLE-MOTION START========================================================
" Use the key to simulate
let g:comfortable_motion_scroll_down_key = "j"
let g:comfortable_motion_scroll_up_key   = "k"
" If your Vim/NeoVim has mouse support, you can get mouse wheel to scroll a window by the following mappings:
noremap <silent> <ScrollWheelDown> :call comfortable_motion#flick(40)<CR>
noremap <silent> <ScrollWheelUp>   :call comfortable_motion#flick(-40)<CR>
" If you would like to use scrolling proportional to the window height, you may use settings such as these:
let g:comfortable_motion_no_default_key_mappings = 1
let g:comfortable_motion_impulse_multiplier      = 1  " Feel free to increase/decrease this value.
nnoremap <silent> <C-d> :call comfortable_motion#flick(g:comfortable_motion_impulse_multiplier * winheight(0) * 2)<CR>
nnoremap <silent> <C-u> :call comfortable_motion#flick(g:comfortable_motion_impulse_multiplier * winheight(0) * -2)<CR>
nnoremap <silent> <C-f> :call comfortable_motion#flick(g:comfortable_motion_impulse_multiplier * winheight(0) * 4)<CR>
nnoremap <silent> <C-b> :call comfortable_motion#flick(g:comfortable_motion_impulse_multiplier * winheight(0) * -4)<CR>
"========================================================COMFORTABLE-MOTION   END=======================================================]

"[=======================================================VIM-BOOKMARKS   START======================================================
highlight BookmarkSign ctermbg=NONE ctermfg=160
highlight BookmarkLine ctermbg=194 ctermfg=NONE
let g:bookmark_sign = '⚑'
let g:bookmark_highlight_lines = 1
"========================================================VIM-BOOKMARKS   END=======================================================]

"[========================================================NERDTREE START=======================================================
map <C-n> :NERDTreeToggle<CR>
" Open a NERDTree automatically when vim starts up if no files were specified
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif
" Close vim if the only window left open is a NERDTree
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif
" Have different highlighting for different file extensions
function! NERDTreeHighlightFile(extension, fg, bg, guifg, guibg)
 exec 'autocmd filetype nerdtree highlight ' . a:extension .' ctermbg='. a:bg .' ctermfg='. a:fg .' guibg='. a:guibg .' guifg='. a:guifg
 exec 'autocmd filetype nerdtree syn match ' . a:extension .' #^\s\+.*'. a:extension .'$#'
endfunction
call NERDTreeHighlightFile('jade', 'green', 'none', 'green', '#151515')
call NERDTreeHighlightFile('ini', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('md', 'blue', 'none', '#3366FF', '#151515')
call NERDTreeHighlightFile('yml', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('config', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('conf', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('json', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('html', 'yellow', 'none', 'yellow', '#151515')
call NERDTreeHighlightFile('styl', 'cyan', 'none', 'cyan', '#151515')
call NERDTreeHighlightFile('css', 'cyan', 'none', 'cyan', '#151515')
call NERDTreeHighlightFile('coffee', 'Red', 'none', 'red', '#151515')
call NERDTreeHighlightFile('js', 'Red', 'none', '#ffa500', '#151515')
call NERDTreeHighlightFile('php', 'Magenta', 'none', '#ff00ff', '#151515')
"=========================================================NERDTREE   END=======================================================]

syntax on
colorscheme onedark
